import Util from './util'

export default class FlatTilesetTool  {
  constructor(options) {
    this.tileset = options.tileset;
    const { Cesium, cesiumViewer } = window
    this.ldCollection = new Cesium.PrimitiveCollection()
    cesiumViewer.scene.primitives.add(this.ldCollection)
    var inforStr = '<div class="drawhelperinfor">' +
      '<input class="heightrange" type="number" value="0"><br/><br/>'+
      '<input type="button" class="btnnormal"  value="确定">' +
      '<input type="button" class="btndanger" value="取消">' +
      '</div>'
    let divCollection = document.getElementsByClassName('drawhelperinfor')
    if (divCollection.length == 0) {
      Util.append(cesiumViewer.container, inforStr)
    }
    this.posarr = []
    this.posarr1 = []
    this.ids = []
    this.polygonCount = 0;
    this.polygonsTexture = null;
    //this.entityIds = [];
    this.canMove = false;
    this.canLeftClick = true;
    this.textureWidth = 4096;
    this.textureHeight = 4096;
    this.initPolygonsTexture();
    this.currentIndexArr = [];

  }



  _convertPos(cartesians,tileInverTransform) {
    if (cartesians &&  cartesians.length>0) {
      let pushPositions = [];
      for (let  n = 0; n < cartesians.length; n++) {
        let pushPos = Cesium.Matrix4.multiplyByPoint(tileInverTransform, cartesians[n], new Cesium.Cartesian3);
        pushPositions.push(pushPos)

      }

      let xarr = []
      let yarr = []

      for (let i = 0; i < pushPositions.length; i++) {
        // xarr.push(pushPositions[i].x)
        // yarr.push(pushPositions[i].y)
        xarr.push(-pushPositions[i].y)
        yarr.push(-pushPositions[i].x)

      }
      let vertxarr = [...xarr];
      let vertyarr =[...yarr];
      xarr.sort( function(a, b) {
        return a - b
      })
      yarr.sort( function(a, b) {
        return a - b
      })


      let polygonBounds = new Cesium.Cartesian4(xarr[0], yarr[0], xarr[xarr.length - 1], yarr[yarr.length - 1])
      return{
        vertxarr:vertxarr,
        vertyarr:vertyarr,
        pushPositions:pushPositions,
        polygonBounds:polygonBounds
      }
    }
  return null;
  }

  _createTexture() {
    const { Cesium, cesiumViewer } = window
    this._float32View = new Float32Array(this.textureWidth*this.textureHeight*4)
    for(let i=0; i<this.textureWidth*this.textureHeight*4; i+=4){
      this._float32View[i] =   0.0
      this._float32View[i+1] = 0.0
      this._float32View[i+2] = 0.0
      this._float32View[i+3] = 0.0

    }
    
    let polygonsTexture = new Cesium.Texture({
      context: cesiumViewer.scene._frameState.context,
      width: this.textureWidth,
      height: this.textureHeight,
      pixelFormat: Cesium.PixelFormat.RGBA,
      pixelDatatype: Cesium.PixelDatatype.FLOAT,
      flipY: false,
      sampler: new Cesium.Sampler({
        wrapS: Cesium.TextureWrap.CLAMP_TO_EDGE,
        wrapT: Cesium.TextureWrap.CLAMP_TO_EDGE,
        minificationFilter: Cesium.TextureMinificationFilter.NEAREST,
        magnificationFilter: Cesium.TextureMagnificationFilter.NEAREST
      })
    })
    polygonsTexture.copyFrom({
      width: this.textureWidth,
      height: this.textureHeight,
      arrayBufferView: this._float32View
    })
    //polygonsTexture.generateMipmap();
    return polygonsTexture;
  }
  
  initPolygonsTexture() {
    if(!this.polygonsTexture){

      this.polygonsTexture = this._createTexture()


      window.pushTileSetParams = {}
      window.pushTileSetParams.tilesetUrl=this.tileset.url;
      window.pushTileSetParams.polygonsTexture = this.polygonsTexture;
      window.pushTileSetParams.isDiscard=true;
      window.pushTileSetParams.isFlat=true;
      window.pushTileSetParams.modelMatrix = this.tileset._root.transform;
    }

  }

  //点在多边形内（不包括在多边形边上）
  isInPolygon(nvert, vertxarr, vertyarr, testx, testy) {
    let i, j, c = 0;
    for (i = 0, j = nvert-1; i < nvert; j = i++) {
      if (( (vertyarr[i]>testy) != (vertyarr[j]>testy) ) &&
        (testx < (vertxarr[j]-vertxarr[i]) * (testy-vertyarr[i]) / (vertyarr[j]-vertyarr[i]) + vertxarr[i]))
        c = !c;
    }
    return c;
  }

  isInPolygon1(nvert, vertxarr, vertyarr, testx, testy) {

    /** 是否正好相交在边上~ */
    let isIntersectOnSection = false
    let nCross = 0
    let p = new Cesium.Cartesian2(testx, testy);
    for (let i = 0; i < nvert; i++) {
      let p1 = new Cesium.Cartesian2(vertxarr[i], vertyarr[i])
      let p2 = new Cesium.Cartesian2(vertxarr[(i + 1) % nvert], vertyarr[(i + 1) % nvert])

      // 求解 y=p.y 与 p1 p2 的交点
      if (p1.y == p2.y) {   // p1p2 与 y=p0.y平行
        continue
      }
      if (p.y < Math.min(p1.y, p2.y)) { // 交点在p1p2延长线上
        continue
      }
      if (p.y > Math.max(p1.y, p2.y)) { // 交点在p1p2延长线上
        continue
      }
// 求交点的 X 坐标  
      let x = (p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x

      /** 是否正好相交在边上~ */
      if (Math.abs(x - p.x) < 10e-4) {
        isIntersectOnSection = true
        break
      }
      if (x > p.x) { // 只统计单边交点
        nCross++
      }
    }
    if (isIntersectOnSection || nCross % 2 == 1) {    // 单边交点为偶数，点在多边形之外
      return true
    } else {
      return false
    }
  }

isInBounds(bounds,testx, testy){
    if (testx > bounds.x && testx< bounds.z && testy > bounds.y && testy < bounds.w) {
      return true;
    }
    return false;
  }



  updatePolygonsTexture(posarr,index,minHeight){
    if(this.currentIndexArr.length > 0){
      for(let i=0; i<this.currentIndexArr.length; i++){
        this._float32View[this.currentIndexArr[i]] =   minHeight;
      }
    }
    else{
      let tileInverTransform = Cesium.Matrix4.inverse(this.tileset._root.transform,new Cesium.Matrix4())
      let obj = this._convertPos(posarr,tileInverTransform);
      const {vertxarr,vertyarr,pushPositions,polygonBounds} = obj;
      let kk=0;
      for(let i=0; i<this.textureWidth; i++){
        for(let j=0; j<this.textureHeight; j++) {
          let px = i-this.textureWidth*0.5;
          let py = this.textureHeight*0.5 - j;
          if(this.isInBounds(polygonBounds,px,py)){
            if(this.isInPolygon(pushPositions.length,vertxarr,vertyarr,px,py)){
              this._float32View[kk] =   minHeight;
              this.currentIndexArr.push(kk);
            }
          }
          kk+=4;
        }
      }
    }


    this.polygonsTexture.copyFrom({
      width: this.textureWidth,
      height: this.textureHeight,
      arrayBufferView: this._float32View
    })
  }

  setPushHeight(index,height){

  }
  

  _showToolBar() {
    const { cesiumViewer } = window
    this.infoDiv = cesiumViewer.container.querySelector('.drawhelperinfor')
    this.infoDiv.style.display = 'block'
    let heightrange = this.infoDiv.querySelector('.heightrange')
    let btnok = this.infoDiv.querySelector('.btnnormal')
    let btncalcel = this.infoDiv.querySelector('.btndanger')
    heightrange.removeEventListener('change', this.changFlatheightHandler)
    heightrange.addEventListener('change', this.changFlatheightHandler)
    btnok.removeEventListener('click', this.okClickHandler)
    btnok.addEventListener('click', this.okClickHandler)
    btncalcel.removeEventListener('click', this.cancelClickHandler)
    btncalcel.addEventListener('click', this.cancelClickHandler)

  }

  changFlatheightHandler=()=>{
    let heightrange = this.infoDiv.querySelector('.heightrange');
    let height = parseFloat(heightrange.value);
    this.updatePolygonsTexture(this.posarr,this.polygonCount, height);

  }


  okClickHandler = () => {
    const { Cesium, cesiumViewer } = window
    console.log(this.posarr);
    let pHierarchy = new Cesium.PolygonHierarchy([...this.posarr])
    let pid = Util.generateGUID();
    this.addPolygonPrimitive({
      hierarchy: pHierarchy,
      color: new Cesium.ColorGeometryInstanceAttribute(0.0,0.0,0.0,0.0),
      id: pid
    })

    this.currentIndexArr.length = 0;
    this.polygonCount++;


        // for (let i = 0; i < this.entityIds.length; i++) {
        //   cesiumViewer.entities.removeById(this.entityIds[i])
        // }
        this.posarr.length = 0
        this.posarr1.length = 0


    this.canLeftClick = true;
    this.infoDiv.style.display = 'none'



  }

  cancelClickHandler = () => {
    const { cesiumViewer } = window
    this.updatePolygonsTexture(this.posarr,this.polygonCount, 0.0);
      // for (let i = 0; i < this.entityIds.length; i++) {
      //   cesiumViewer.entities.removeById(this.entityIds[i])
      // }
    this.currentIndexArr.length = 0;
    this.canLeftClick = true;
      this.posarr.length = 0
      this.posarr1.length = 0


    this.infoDiv.style.display = 'none'
  }



  //添加整个
  addPolygonPrimitive(e) {
    this.ldCollection.add(new Cesium.ClassificationPrimitive({
      geometryInstances: new Cesium.GeometryInstance({
        id: e.id,
        geometry: new Cesium.PolygonGeometry({
          polygonHierarchy: e.hierarchy,
        }),
        attributes: {
          color: e.color,
          distanceDisplayCondition: new Cesium.DistanceDisplayConditionGeometryInstanceAttribute(0, 5000.0),
        },
      }),
      classificationType: Cesium.ClassificationType.BOTH,
      releaseGeometryInstances: false
    }))
  }

  addTempEntity() {
    const { Cesium, cesiumViewer } = window
    let entity = cesiumViewer.entities.getById('tempbox')
    if (entity) {
      return
    }
    cesiumViewer.entities.add({
      id: 'tempbox',
      polyline: {
        positions: new Cesium.CallbackProperty(() =>{
          if(this.posarr1.length > 1){
            return [...this.posarr1]
          } else {
            return null
          }
        }, false),
        clampToGround: true,
        width: 2.0,
        material: Cesium.Color.AQUA,
        show: true
      }
    })
  }

  addHandler() {
    const { Cesium, cesiumViewer } = window

    this.handler.setInputAction((movement) => {
      if(!this.canLeftClick) return;
      let pickedFeature = cesiumViewer.scene.pick(movement.position)
      let cartesian = null;
      if (!Cesium.defined(pickedFeature) && !(pickedFeature instanceof Cesium.Cesium3DTileFeature)) {
        let ray=cesiumViewer.camera.getPickRay(movement.position);
         cartesian = cesiumViewer.scene.globe.pick(ray, cesiumViewer.scene);
      }
      else{
         cartesian = cesiumViewer.scene.pickPosition(movement.position)
      }
      // let cartesian = cesiumViewer.camera.pickEllipsoid(movement.position, cesiumViewer.scene.globe.ellipsoid);


      this.posarr.push(cartesian)
      this.posarr1.push(Cesium.Cartesian3.clone(cartesian))


      // let pid = Util.generateGUID();
      //   let entity = cesiumViewer.entities.add({
      //     id: pid,
      //     position: cartesian,
      //     billboard: {
      //       image: 'textures/circle_red.png',
      //       disableDepthTestDistance: Number.POSITIVE_INFINITY,
      //       heightReference: Cesium.HeightReference.NONE
      //     }
      //   })
      //   this.entityIds.push(pid)
         this.canMove = true;

    }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
    let lastX = 0
    let lastY = 0
    this.handler.setInputAction((movement) => {
      if (!this.canMove)  return;
      if (Math.abs(lastX - movement.endPosition.x) < 16 && Math.abs(lastY - movement.endPosition.y) < 16) {
        return;
      }
      let pickedFeature = cesiumViewer.scene.pick(movement.endPosition)
      let cartesian = null;
      if (!Cesium.defined(pickedFeature) && !(pickedFeature instanceof Cesium.Cesium3DTileFeature)) {
        let ray=cesiumViewer.camera.getPickRay(movement.endPosition);
        cartesian = cesiumViewer.scene.globe.pick(ray, cesiumViewer.scene);
      }
      else{
        cartesian = cesiumViewer.scene.pickPosition(movement.endPosition)
      }
      //let cartesian = cesiumViewer.camera.pickEllipsoid(movement.endPosition, cesiumViewer.scene.globe.ellipsoid);

      // let ray=cesiumViewer.camera.getPickRay(movement.endPosition);
      // let cartesian = cesiumViewer.scene.globe.pick(ray, cesiumViewer.scene);
      if(this.posarr1.length>1){
        this.posarr1.pop();
      }
        this.posarr1.push(cartesian)
      lastX = movement.endPosition.x
      lastY = movement.endPosition.y
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)

    this.handler.setInputAction((movement) => {
      if(this.posarr.length<3) return;

      this.canMove = false;
      this.canLeftClick = false;
      let cartesian = this.posarr[0]

      // this.posarr.push(cartesian)
      this.posarr1.pop();
      this.posarr1.push(Cesium.Cartesian3.clone(cartesian))


      this._showToolBar()
      let minHeight = 9999.0;
      for(let i=0; i<this.posarr.length; i++){
        let cartographicPosition = Cesium.Ellipsoid.WGS84.cartesianToCartographic(this.posarr[i]);
        if(cartographicPosition.height < minHeight){
          minHeight = cartographicPosition.height;
        }
      }
      let heightrange = this.infoDiv.querySelector('.heightrange')
      heightrange.value = minHeight.toFixed(2);
      this.updatePolygonsTexture(this.posarr,this.polygonCount,minHeight);

    }, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
    this.addTempEntity()
  }

  deletePolygon() {
    const { Cesium, cesiumViewer } = window
    this.handler.setInputAction((movement) => {
      let pickedObject = cesiumViewer.scene.pick(movement.position)
      if (Cesium.defined(pickedObject) && pickedObject.primitive instanceof Cesium.ClassificationPrimitive) {
        for (let i = 0; i < this.ldCollection.length; ++i) {
          if (pickedObject.id == this.ids[i]) {
            this.ldCollection.remove(pickedObject.primitive)
            this.ids.splice(i, 1)
            break
          }
        }
      }

    }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
  }

  setPolygonsVisible(visible) {

    for (let i = 0; i < this.ldCollection.length; ++i) {
      let p = this.ldCollection.get(i)
      let attributes = p.getGeometryInstanceAttributes(this.ids[i])
      attributes.color = [attributes.color[0], attributes.color[1],
        attributes.color[2], visible ? 128 : 0]
    }
  }

  removeHandler() {
    const { Cesium, cesiumViewer } = window
    this.posarr.length = 0
    this.posarr1.length = 0
    if (this.handler && !this.handler.isDestroyed()) {
      this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
      this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
    }
  }

  destoryHandler() {
    if (this.handler && !this.handler.isDestroyed()) {
      this.handler.destroy();
    }
  }

  fromGeoJson(jsonData){
    this.ldCollection.removeAll();
    for(let i=0; i<jsonData.features.length; i++){
      let coordinates = jsonData.features[i].geometry.coordinates[0];
      let arr = [];
      for(let j=0; j<coordinates.length; j++){
        arr.push(coordinates[j][0],coordinates[j][1]);
      }

        this.posarr =  Cesium.Cartesian3.fromDegreesArray(arr)

     this.updatePolygonsTexture(this.posarr,0,1.0);


    }
  }


}
